package org.xs.web.http.provider;

import java.net.MalformedURLException;
import java.net.URL;
import java.util.Date;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.xs.web.http.AjaxResponse;
import org.xs.web.http.HtmlResponse;
import org.xs.web.http.InvokeContext;
import org.xs.web.http.JsonResponse;
import org.xs.web.http.NotfoundResponse;
import org.xs.web.http.S;
import org.xs.web.http.StreamingResponse;
import org.xs.web.http.XSResponse;
import org.xs.web.http.XSRules;
import org.xs.web.http.i18n.Location;
import org.xs.web.http.provider.servlet.HTTPFilterProvider;
import org.xs.web.http.validate.FieldErrorMsg;
import org.xs.web.http.validate.ValidateExecutor;
import org.xs.web.util.Console;
import org.xs.web.util.DateFormat;
 

public class HTTPFilter extends HTTPFilterProvider{
	private static Pattern pattern = Pattern.compile("[^\\.]\\.json$|[^\\.]\\.html$|[^\\.]\\.htm$|[^\\.]\\.xhtml|^/ajax/.+\\.js$");
	private static Pattern ajaxResource = Pattern.compile("^/ajax/(.+)\\.js$");
	@Override
	public void doService(HTTPRequest request, HTTPResponse response) {
		long timeNow = Console.timeNow();
		try{
			String resName = isResource(request.url());
			XSResponse xsresp = null;
			List<FieldErrorMsg> fieldError = validateParams(request);
			if(fieldError.size() > 0){
				if(request.isJson()){
					xsresp = new JsonResponse(fieldError);
				}else{
					S.set("M",fieldError);
					xsresp = new HtmlResponse(XSRules.validateMsgHtml);
				}
			}else{
				if(resName != null){
					xsresp = processResource(request, resName);
				}else{
					xsresp = executeAction();
				}
			}
			xsresp.apply(response);
		}finally{
			long consume = Console.timeNow() - timeNow;
			Console.log(request.getMethod() +" "+request.getPath()+" took "+consume +" Milliseconds");
		}
	}
	public String isResource(String path){
		try {
			Matcher mather =  ajaxResource.matcher(path);
			if(mather.find()){
				return mather.group(1);
			}
		} catch (Exception e) {
		}
		return null;
	}
	 
	
	protected XSResponse processResource(HTTPRequest request,String resName){
		
		if(XSRules.xsAjax.equals(resName)){
			String value = request.header("If-Modified-Since").value();
			Location loc = Location.create();
			Date date = DateFormat.toGMTDate(value);
			if(date == null || loc.lastModify() / 1000 > date.getTime() / 1000){
				return new AjaxResponse(loc.message().toJs(),200,new HTTPHeader[]{new HTTPHeader("Last-Modified", DateFormat.toGMTString(new Date(loc.lastModify()))),new HTTPHeader("Expires", DateFormat.toGMTString(DateFormat.dateRange(10)))});
			}
			return new StreamingResponse(new byte[0],304);
		}
		return new NotfoundResponse(XSRules.getNotfoundMessage());
	}
	
	public List<FieldErrorMsg> validateParams(HTTPRequest request){
		return ValidateExecutor.validate(request.controllerName(), request.actionName(), S.params());
	}
	
	
	protected XSResponse executeAction(){
		XSResponse response = null;
		boolean notfound = notFoundResouce();
		Object cont = S.getBean(S.request().controllerName());
		if(cont == null){
			if(notfound){
				response = new NotfoundResponse(XSRules.getNotfoundMessage());
			}else{
				response = new HtmlResponse(S.request().tirmPath());
			}
		}
		if(cont !=null && XSRules.isXSControoler(cont.getClass())){
			InvokeContext ic = XSRules.invokeActoin(S.request().controllerName(), cont, S.request().actionName(),notfound);
			if(ic.getRes() instanceof XSResponse){
				response = (XSResponse) ic.getRes();
			}else{
				if(ic.isHaveAction() && ic.isExecute() && S.request().isJson()){
					response = new JsonResponse(S.getContext());
				}else if(S.request().isHtml() && !notfound){
						response = new HtmlResponse(S.request().tirmPath());
				}
			}
		}
		if(response == null){
			response = new NotfoundResponse(XSRules.getNotfoundMessage());
		}
		return response;
	}
	
	public boolean notFoundResouce(){
		try {
			URL url = getServletContext().getResource(S.request().getDelegate().getServletPath());
			return url == null;
		} catch (MalformedURLException e) {
			 return true;
		}
	}
	
	@Override
	public boolean isXsService(String path) {
		
		return  pattern.matcher(path).find();
	}

	@Override
	public void boot(){
		
	}
	
	
	
	
	
	
}
